package huriezy.quickcontacts.models.managers;

import huriezy.quickcontacts.models.LogDebug;
import huriezy.quickcontacts.models.interfaces.IPictureManager;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.provider.MediaStore;

public class ContactPictureManager implements IPictureManager {

	private final int			THUMBNAIL_SIZE		= 1024;

	public static final String	PICTURE_FILE_NAME	= "Contact_picture_temp";

	private final Context		parentContext;

	public ContactPictureManager(Context parentContext) {
		this.parentContext = parentContext;
	}

	/**
	 * Creates a file that saves a compressed {@link Bitmap} picture.
	 * 
	 * @return the {@link File} object relative to the image
	 * @throws IOException
	 */
	public File saveTempImageFile(Bitmap bitmapPicture) {
		File storageDir = parentContext.getExternalFilesDir(null);
		File result = new File(storageDir, PICTURE_FILE_NAME + ".png");
		try {
			FileOutputStream out = new FileOutputStream(result);
			bitmapPicture.compress(Bitmap.CompressFormat.PNG, 90, out);
			out.close();
		}
		catch (IOException e) {
			LogDebug.error("Cannot save bitmap image to the donate location : " + result.getAbsolutePath(),
					parentContext);
		}
		if (result != null) {
			String logDesc = (result == null) ? "File not created" : "File created : " + result.getAbsolutePath();
			LogDebug.info(logDesc, getClass());
		}
		return result;
	}

	/**
	 * Retrieve full internal path from an incoming {@link Intent}. If the Uri
	 * point to an external link (ex : https address), a local file is created.
	 * 
	 * @param uri
	 *            the concerned {@link Uri}
	 * @return a {@link String} representing its full path
	 */
	public String getImagePath(Uri pictureFileURI) {
		String result = null;
		LogDebug.info("Retrieved picture intent Uri : " + pictureFileURI, getClass());
		if (pictureFileURI == null) {
			LogDebug.warn("Cannot retrieve Uri from explorer", getClass());
		}
		else {
			String[] projection = { MediaStore.Images.Media.DATA };
			Cursor cursor = parentContext.getContentResolver().query(pictureFileURI, projection, null, null, null);

			int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
			cursor.moveToFirst();

			result = cursor.getString(column_index);
			cursor.close();

			LogDebug.info("Retrieved picture absolute path : " + result, getClass());
		}
		return result;
	}

	/**
	 * Reduce a picture from a donate image file
	 * 
	 * @param parentImageView
	 * @return
	 * @throws IOException
	 */
	public Bitmap scaleImage(Uri imageUri) throws IOException {
		Bitmap result = null;
		LogDebug.info("Try to scale picture to user image view...", getClass());

		Bitmap bitmap =  decodeBitmapResized(imageUri);
		result = cropImage(bitmap);

		LogDebug.info("Picture scaled, result is " + result, getClass());
		return result;
	}
	
	/**
	 * 
	 * @param imageUri
	 * @return
	 * @throws IOException
	 */
	private Bitmap decodeBitmapResized(Uri imageUri) throws IOException{
		Bitmap result = null;
		InputStream inStream = parentContext.getContentResolver().openInputStream(imageUri);

		BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
		if (inStream != null) {
			bitmapOptions.inJustDecodeBounds = true;
			BitmapFactory.decodeStream(inStream, null, bitmapOptions);
			if ((bitmapOptions.outWidth == -1) || (bitmapOptions.outHeight == -1)) {
				return null;
			}
		}

		int originalSize = (bitmapOptions.outHeight > bitmapOptions.outWidth) ? bitmapOptions.outHeight
				: bitmapOptions.outWidth;
		double ratio = (originalSize > THUMBNAIL_SIZE) ? (originalSize / THUMBNAIL_SIZE) : 1.0;
		int squareRatio = Integer.highestOneBit((int) Math.floor(ratio));
		if (squareRatio < 2) {
			squareRatio = 2;
		}
		LogDebug.info("squareRatio : " + squareRatio, getClass());
		
		bitmapOptions = new BitmapFactory.Options();
		bitmapOptions.inSampleSize = squareRatio;
		inStream = parentContext.getContentResolver().openInputStream(imageUri);
		if (inStream != null) {
			result = BitmapFactory.decodeStream(inStream, null, bitmapOptions);
			inStream.close();
		}
		return result;
	}

	/**
	 * 
	 * @param originalPicture
	 * @return
	 */
	private Bitmap cropImage(Bitmap originalPicture) {
		Bitmap result = null;
		if (originalPicture != null) {
			int imageWidth = originalPicture.getWidth();
			int imageHeight = originalPicture.getHeight();
			int xTranslate = 0;
			int yTranslate = 0;
			int squareSize = 0;

			if (imageHeight > imageWidth) {
				yTranslate = (imageHeight / 2) - (imageWidth / 2);
				squareSize = imageWidth;
			}
			else if (imageWidth > imageHeight) {
				xTranslate = (imageWidth / 2) - (imageHeight / 2);
				squareSize = imageHeight;
			}
			else {
				squareSize = imageHeight;
			}

			if(squareSize > 1000){
				xTranslate = xTranslate / 2;
				yTranslate = yTranslate / 2;
				squareSize = squareSize / 2;				
			}

			StringBuilder builder = new StringBuilder();
			builder.append("Bitmap -> ");
			builder.append(originalPicture);
			builder.append(", imageWidth : ");
			builder.append(imageWidth);
			builder.append(", imageHeight : ");
			builder.append(imageHeight);			
			builder.append(", x : ");
			builder.append(xTranslate);
			builder.append(", y : ");
			builder.append(yTranslate);
			builder.append(", size : ");
			builder.append(squareSize);
			LogDebug.info(builder.toString(), getClass());
			
			result = Bitmap.createBitmap(originalPicture, xTranslate, yTranslate, squareSize, squareSize);

		}
		return result;
	}
}
